//
//  MKChainedPropertyClass.m
//  ObjectCChained
//
//  Created by sny on 2018/5/21.
//  Copyright © 2018年 HuangYangYang. All rights reserved.
//

#import "MKChainedPropertyClass.h"

@implementation MKChainedPropertyClass

- (void)setValueWithCount:(NSUInteger)count WithParams:(NSArray *)params withProperties:(objc_property_t *)properties{
    
    self.chainedParamsType = MKChainedParamsArray; //当前的传入参数的类型是数组
    
    for (int i = 0; i < count; i++) {
        objc_property_t property = properties[i];
        
        const char *propertyName = property_getName(property);
        const char *propertyType_Attributes = property_getAttributes(property);
        
        NSString *propertyType = [MKChainedCheckPropertyClass PropertiesName:propertyType_Attributes];
        
        NSString *paramsType = [MKChainedCheckPropertyClass ParamsItemsName:params[i]];
        
        BOOL isSame = [MKChainedCheckPropertyClass checkNODifferenceWithPropertyName:propertyType WithParamsName:paramsType AndProperty:[NSString stringWithUTF8String:propertyName]];
        
        if (isSame) {
            [self setValue:params[i] forKey:[NSString stringWithUTF8String:propertyName]];
        }
    }
}

- (void)setValueWithCount:(NSUInteger)count WithDictionaryParams:(NSDictionary *)params withProperties:(objc_property_t *)properties {
    
    self.chainedParamsType = MKChainedParamsDictionary; //当前的传入参数的类型是字典
    
    for (int i = 0; i < count; i++){
        
        objc_property_t property = properties[i];
        
        //1.拿到属性名称
        const char *propertyName = property_getName(property);
        //2.拿到属性的类型
        const char *propertyType_Attributes = property_getAttributes(property);
        NSString *propertyType = [MKChainedCheckPropertyClass PropertiesName:propertyType_Attributes];
        
        if (self.allowEmpty == NO) {
            //不允许空值存在的情况下 我们要检测下字典中是否存在相应的key
            //3.取出所有的key值
            NSArray *keyArray = [params allKeys];
            //4.如果属性的名称不在字典key的数组当中
            if ([keyArray indexOfObject:[NSString stringWithUTF8String:propertyName]] == NSNotFound) {
                //抛出错误 字典中不存在这个key值
                [MKChainedClassError showErrorWithMKChainedClassErrorType:MKChainedClassErrorKey WithErrorValue:[NSString stringWithUTF8String:propertyName]];
                return;
            }
        }
        
        NSString *paramsType = [MKChainedCheckPropertyClass ParamsItemsName:params[[NSString stringWithUTF8String:propertyName]]];
        
        BOOL isSame = [MKChainedCheckPropertyClass checkNODifferenceWithPropertyName:propertyType WithParamsName:paramsType AndProperty:[NSString stringWithUTF8String:propertyName]];
        
        if (isSame) {
            [self setValue:params[[NSString stringWithUTF8String:propertyName]] forKey:[NSString stringWithUTF8String:propertyName]];
        }
    }
}

@end

@implementation MKChainedCheckPropertyClass

//显示获取当前类的属性类型
+ (NSString *)PropertiesName:(const char * _Nullable)property_Attributes {
    
    NSString *property_data_type = nil;
    
    if (property_Attributes[1] == '@') {
        char * occurs1 =  strchr(property_Attributes, '@');
        char * occurs2 =  strrchr(occurs1, '"');
        char dest_str[40]= {0};
        strncpy(dest_str, occurs1, occurs2 - occurs1);
        char * realType = (char *)malloc(sizeof(char) * 50);
        int j = 0, len = (int)strlen(dest_str);
        for (int i = 0; i < len; i++) {
            if ((dest_str[i] >= 'a' && dest_str[i] <= 'z') || (dest_str[i] >= 'A' && dest_str[i] <= 'Z')) {
                realType[j++] = dest_str[i];
            }
        }
        property_data_type = [NSString stringWithFormat:@"%s", realType];
        free(realType);
        
    }else {
        //Otherwise, take the second subscript character for comparing to the @encode()
        char * realType = [self getPropertyRealType:property_Attributes];
        property_data_type = [NSString stringWithFormat:@"%s", realType];
    }
    return property_data_type;
}

+ (NSString *_Nullable)ParamsItemsName:(id _Nullable )paramsItems {
    if ([paramsItems isKindOfClass:[NSString class]]) {
        
        return MKCLHAINEDCLASS_PROPERTY_TYPE_NSSRTING;
    }
    
    if ([paramsItems isKindOfClass:[NSArray class]]) {
        
        return MKCLHAINEDCLASS_PROPERTY_TYPE_NSSARRAY;
    }
    
    if ([paramsItems isKindOfClass:[NSNumber class]]) {
        
        return MKCLHAINEDCLASS_PROPERTY_TYPE_NSNUMBER;
    }
    
    return @"";
}

//检查赋值与被赋值的属性是否一致
+ (BOOL)checkNODifferenceWithPropertyName:(NSString *_Nullable)propertyName
                           WithParamsName:(NSString *_Nullable)paramsName
                              AndProperty:(NSString *_Nullable)property{
    
    if ([propertyName isEqualToString:paramsName]) {
        return YES;
        
    }else if ([paramsName isEqualToString:MKCLHAINEDCLASS_PROPERTY_TYPE_NSNUMBER] && [[MKChainedCheckPropertyClass basePropertyList] indexOfObject:propertyName] != NSNotFound) {
     //如果数组中的对象为number的时候
        return YES;
    }else{
        [MKChainedClassError showErrrorPropertyName:property ErrorParamsProperty:paramsName CorrectParamsName:propertyName];
        return NO;
    }
}

//其他的类型判断
+ (char *)getPropertyRealType:(const char * _Nullable)property_Attributes {
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(int))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_INT;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(char))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_CHAR;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(short))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_SHORT;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(long))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_LONG;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(unsigned char))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_UNSIGNEDCHAR;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(unsigned int))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_UNSIGNEDINT;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(unsigned short))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_UNSIGNEDSHORT;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(unsigned long))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_UNSIGNEDLONG;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(float))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_FLOAT;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(double))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_DOUBLE;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(_Bool))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_BOOL;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(bool))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_BOOL;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(void))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_VOID;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(char *))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_CHARALL;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(id))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_ID;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(Class))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_CLASS;}
    
    if (MKChainedClass_Compare(property_Attributes[1], @encode(SEL))) {return MKCLHAINEDCLASS_PROPERTY_TYPE_SEL;}
    
    return "";
}

+ (NSArray *)basePropertyList {
    return @[[NSString stringWithFormat:@"%s",MKCLHAINEDCLASS_PROPERTY_TYPE_INT],
             [NSString stringWithFormat:@"%s",MKCLHAINEDCLASS_PROPERTY_TYPE_FLOAT],
             [NSString stringWithFormat:@"%s",MKCLHAINEDCLASS_PROPERTY_TYPE_DOUBLE],
             [NSString stringWithFormat:@"%s",MKCLHAINEDCLASS_PROPERTY_TYPE_LONG],
             [NSString stringWithFormat:@"%s",MKCLHAINEDCLASS_PROPERTY_TYPE_BOOL]];
}

@end

